_editor_class={}

_infinite=4294967296

function task._Wait(t)
	t=t or 0
	t=max(0,int(t))
	for i=1,t do coroutine.yield() end
end

_straight=Class(bullet)
function _straight:init(imgclass,index,x,y,v,angle,aim,omiga,stay,destroyable)
	self.x=x self.y=y
	SetV2(self,v,angle,true,aim)
	self.omiga=omiga
	bullet.init(self,imgclass,index,stay,destroyable)
end

function _create_bullet_group(style,color,x,y,n,t,v1,v2,angle,da,aim,omiga,stay,des,enemy)
	if n>=1 then
		New(_bullet_shooter,function()
			local dv=(v2-v1)/n
			local da=da/n
			angle=angle+da*(-n/2+0.5)
			v1=v1+dv*0.5
			if aim then angle=angle+Angle(x,y,lstg.player.x,lstg.player.y) end
			for i=0,n-1 do
				last=New(_straight,style,color,x,y,v1+dv*i,angle+da*i,false,omiga,stay,des)
				task._Wait(t)
			end
		end,enemy)
	end
end

function _play_music(name)
	local _,bgm=EnumRes('bgm')
	for _,v in pairs(bgm) do StopMusic(v) end
	PlayMusic(name)
end
function _pause_music()
	local _,bgm=EnumRes('bgm')
	for _,v in pairs(bgm) do PauseMusic(v) end
end
function _resume_music()
	local _,bgm=EnumRes('bgm')
	for _,v in pairs(bgm) do ResumeMusic(v) end
end
function _stop_music()
	local _,bgm=EnumRes('bgm')
	for _,v in pairs(bgm) do StopMusic(v) end
end

_object=Class(object)
function _object:frame()
	if self.hp<=0 then Kill(self) end
	task.Do(self)
end
function _object:render()
	SetImgState(self,self._blend,self._a,self._r,self._g,self._b)
	DefaultRenderFunc(self)
end
function _object:set_color(blend,a,r,g,b)
	self._blend,self._a,self._r,self._g,self._b=blend,a,r,g,b
end
function _object:take_damage(dmg)
	self.hp=self.hp-dmg
end
function _object:colli(other)
	if self.group==GROUP_ENEMY then
		if other.dmg then
			Damage(self,other.dmg)
			if self._master and self._dmg_transfer and IsValid(self._master) then
				Damage(self._master,other.dmg*self._dmg_transfer)
			end
		end
		Kill(other)
		if not other.mute then
			if self.hp>self.maxhp*0.2 then PlaySound('damage00',0.4,self.x/200)
			else PlaySound('damage01',0.8,self.x/200) end
		end
	end
end
function _object:del()
	if ParticleGetn(self)>0 then misc.KeepParticle(self) end
	_del_servants(self)
	New(bubble3,self.img,self.x,self.y,self.rot,self.dx,self.dy,self.omiga,15,self.hscale,self.hscale,
		Color(self._a,self._r,self._g,self._b),Color(0,self._r,self._g,self._b),self.layer,self._blend)
end
function _object:kill()
	if ParticleGetn(self)>0 then misc.KeepParticle(self) end
	_kill_servants(self)
	New(bubble3,self.img,self.x,self.y,self.rot,self.dx,self.dy,self.omiga,15,self.hscale,self.hscale,
		Color(self._a,self._r,self._g,self._b),Color(0,self._r,self._g,self._b),self.layer,self._blend)
end

bubble3=Class(object)

function bubble3:init(img,x,y,rot,vx,vy,omiga,life_time,size1,size2,color1,color2,layer,blend)
	self.img=img
	self.x=x
	self.y=y
	self.rot=rot
	self.vx=vx
	self.vy=vy
	self.omiga=omiga
	self.group=GROUP_GHOST
	self.life_time=life_time
	self.size1=size1
	self.size2=size2
	self.color1=color1
	self.color2=color2
	self.layer=layer
	self.blend=blend or ''
end

function bubble3:render()
	local t=(self.life_time-self.timer)/self.life_time
	self.hscale=self.size1*t+self.size2*(1-t)
	self.vscale=self.hscale
	local c=self.color1*t+self.color2*(1-t)
	SetImgState(self,self.blend,c:ARGB())
	DefaultRenderFunc(self)
end

function bubble3:frame()
	if self.timer==self.life_time-1 then Del(self) end
end

_bullet_shooter=Class(object)
function _bullet_shooter:init(f,enemy)
	self.group=GROUP_INDES
	self.enemy=enemy
	task.New(self,f)
end
function _bullet_shooter:frame()
	if not (IsValid(self.enemy) or self.enemy==stage.current_stage) then
		Del(self)
	else
		task.Do(self)
		if coroutine.status(self.task[1])=='dead' then Del(self) end
	end
end

function _clear_bullet(convert,clear_indes)
	if convert then New(bullet_killer,lstg.player.x,lstg.player.y,clear_indes)
	else New(bullet_deleter,lstg.player.x,lstg.player.y,clear_indes) end
end

function laser:_TurnOn(t,sound,wait)
	t=t or 30
	t=max(1,int(t))
	if sound then PlaySound('lazer00',0.25,self.x/200) end
	self.counter=t
	self.da=(1-self.alpha)/t
	self.dd=(self.d0-self.d)/t
	if task.GetSelf()==self and wait then task.Wait(t) end
end
function laser:_TurnHalfOn(t,wait)
	t=t or 30
	t=max(1,int(t))
	self.counter=t
	self.da=(0.5-self.alpha)/t
	self.dd=(0.5*self.d0-self.d)/t
	if task.GetSelf()==self and wait then task.Wait(t) end
end
function laser:_TurnOff(t,wait)
	t=t or 30
	t=max(1,int(t))
	self.counter=t
	self.da=-self.alpha/t
	self.dd=-self.d/t
	if task.GetSelf()==self and wait then task.Wait(t) end
end
function _init_item(self)
	if lstg.var.is_practice then
		item.PlayerInit()
		if self.item_init then
			for k,v in pairs(self.item_init) do
				lstg.var[k]=v
			end
		end
	else
		if self.number==1 then
			item.PlayerInit()
			if self.group.item_init then
				for k,v in pairs(self.group.item_init) do
					lstg.var[k]=v
				end
			end
		end
	end
end

function _kill(unit,trigger)
	if trigger then Kill(unit) else unit.status='kill' end
end

function _del(unit,trigger)
	if trigger then Del(unit) else unit.status='del' end
end

_can_be_master={[_object]=true,[enemy]=true,[boss]=true}
_can_be_servant={[_object]=true,[enemy]=true,[laser]=true,[bullet]=true,[img_class]=true}
function _connect(master,servant,dmg_transfer,con_death)
	if IsValid(master) and IsValid(servant) then
		if (not _can_be_master[master.class.base]) or (not _can_be_servant[servant.class.base]) then
			error('connect type error')
		end
		if con_death then table.insert(master._servants,servant) end
		servant._master=master
		servant._dmg_transfer=dmg_transfer
	end
end
function _set_rel_pos(servant,x,y,rot,follow_rot)
	if servant._master and IsValid(servant._master) then
		local master=servant._master
		if follow_rot then
			x,y=x*cos(master.rot)-y*sin(master.rot),x*sin(master.rot)+y*cos(master.rot)
			rot=rot+master.rot
		end
		servant.x=master.x+x
		servant.y=master.y+y
		servant.rot=rot
	end
end
function _kill_servants(master)
	for k,v in pairs(master._servants) do if IsValid(v) then Kill(v) end end
	master._servants={}
end
function _del_servants(master)
	for k,v in pairs(master._servants) do if IsValid(v) then Del(v) end end
	master._servants={}
end

function _LoadImageFromFile(teximgname,filename,mipmap,a,b,rect,edge)
	LoadTexture(teximgname,filename,mipmap)
	local w,h=GetTextureSize(teximgname)
	LoadImage(teximgname,teximgname,edge,edge,w-edge*2,h-edge*2,a,b,rect)
end